package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sc.nft.config.hna.HnaConfig;
import com.sc.nft.config.sand.SandConfig;
import com.sc.nft.config.sand.SandPayUtil;
import com.sc.nft.dao.*;
import com.sc.nft.dto.HnaRefundDto;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.RefundDTO;
import com.sc.nft.entity.dto.RefundOrderPageDTO;
import com.sc.nft.entity.dto.TripartitePayRefundListDTO;
import com.sc.nft.entity.vo.PayOrderVO;
import com.sc.nft.entity.vo.RefundOrderPageVO;
import com.sc.nft.enums.OrderStatusEnum;
import com.sc.nft.enums.PayStatusEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.HfPayHelper;
import com.sc.nft.helper.LlPayHelper;
import com.sc.nft.service.DeveloperBackstageService;
import com.sc.nft.service.UserHnaExtService;
import com.sc.nft.util.OrderNoUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Service
public class DeveloperBackstageServiceImpl implements DeveloperBackstageService {
    private final OrderDao orderDao;
    private final SecondOrderDao secondOrderDao;
    private final SecondEquityPropsOrderDao secondEquityPropsOrderDao;
    private final RoughStoneOrderDao refundOrderPage;
    private final UserInfoDao userInfoDao;
    private final PayOrderDao payOrderDao;
    private final LlPayHelper llPayHelper;
    private final HfPayHelper hfPayHelper;
    private final HnaConfig hnaConfig;
    private final UserHnaExtService userHnaExtService;
    private final CollectiveOrderDao collectiveOrderDao;
    @Override
    public IPage<RefundOrderPageVO> refundOrderPage(RefundOrderPageDTO request) {
        UserInfo oneByUserTel = userInfoDao.getOneByUserTel(request.getUserTel());
        if (BeanUtil.isEmpty(oneByUserTel)) {
            throw new GlobalRunTimeException("用户不存在");
        }
        // 根据类型不同找不同的表,但是本质上他的返回数据是一致的
        IPage<RefundOrderPageVO> page = null;
        switch (request.getRefundTypeEnum()) {
            case FIRST_PUBLISH:
                if (request.getStatus()==null) {
                    request.setStatus(OrderStatusEnum.CLOSE);
                }
                if (request.getStatus()==OrderStatusEnum.ALL) {
                    request.setStatus(null);
                }
                page=orderDao.refundOrderPage(request,oneByUserTel.getId());
                break;
            case SECOND_PUBLISH:
                if (request.getStatus()==null) {
                    request.setStatus(OrderStatusEnum.OVERDUE);
                }
                if (request.getStatus()==OrderStatusEnum.ALL) {
                    request.setStatus(null);
                }
                page=secondOrderDao.refundOrderPage(request,oneByUserTel.getId());
                break;
            case ROUGH_PUBLISH:
                if (request.getStatus()==null) {
                    request.setStatus(OrderStatusEnum.CLOSE);
                }
                if (request.getStatus()==OrderStatusEnum.ALL) {
                    request.setStatus(null);
                }
                page=refundOrderPage.refundOrderPage(request,oneByUserTel.getId());
                break;
            case PROP_PUBLISH:
                if (request.getStatus()==null) {
                    request.setStatus(OrderStatusEnum.CLOSE);
                }
                if (request.getStatus()==OrderStatusEnum.ALL) {
                    request.setStatus(null);
                }
                page=secondEquityPropsOrderDao.refundOrderPage(request,oneByUserTel.getId());
                break;
            case COLLECTIVE_SALE:
                if (request.getStatus()==null) {
                    request.setStatus(OrderStatusEnum.CLOSE);
                }
                if (request.getStatus()==OrderStatusEnum.ALL) {
                    request.setStatus(null);
                }
                page=collectiveOrderDao.refundOrderPage(request,oneByUserTel.getId());
                break;
            default:
                break;
        }
        return page;
    }

    @Override
    public List<PayOrderVO> tripartitePayRefundList(TripartitePayRefundListDTO request) {
        return payOrderDao.tripartitePayRefundList(request);
    }

    @Override
    public void refund(RefundDTO request) {
        // 根据不同的类型找不同的资源,退款是失败要给描述.
        PayOrder payOrder = payOrderDao.getById(request.getId());
        String userTelpayOrder = userInfoDao.getUserTelById(payOrder.getUserId());
        if (BeanUtil.isEmpty(payOrder)) {
            throw new GlobalRunTimeException("订单不存在");
        }

        // 记录退款日志.
        // 退款请求日志结果
        String result=null;
        switch (payOrder.getPayType()) {
        case AL_PAY:
                throw new GlobalRunTimeException("当前不支持支付宝退款");
            case SAND_FAST_PAY:
                throw new GlobalRunTimeException("当前不支持银联退款");
            case SAND_CLOUD_PAY:
                throw new GlobalRunTimeException("当前不支持云闪付退款");
            case AL_PAY_WEB:
                throw new GlobalRunTimeException("当前不支持支付宝H5退款");
            case FAST_PAY:
                // 杉德
                result = sandRefund(payOrder);
                break;
            case WALLET_PAY:
                throw new GlobalRunTimeException("当前不支持余额支付退款");
            case HF_FAST_PAY:
                throw new GlobalRunTimeException("当前不支持汇付收银台退款");
            case SAND_BALANCE_PAY:
                // 杉德余额支付
                 result = sandRefund(payOrder);
                break;
            case APPLE_PAY:
                throw new GlobalRunTimeException("当前不支持苹果支付退款");
            case LL_PAY:
                // 连连
                result = otherRefund(payOrder);
                break;
            case HNA_PAY:
                // 新生
                result = otherRefund(payOrder);
                break;
            case WX_PAY:
                throw new GlobalRunTimeException("当前不支持微信支付退款");
            case BALANCE_ONLY:
                throw new GlobalRunTimeException("当前不支持仅余额支付退款");
            default:
                break;
        }

        // 记录退款日志
        PayRefund payRefund=new PayRefund();
        payRefund.setPayOrderId(request.getId());
        payRefund.setUserTel(userTelpayOrder);
        payRefund.setTradeNo(payOrder.getTradeNo());
        payRefund.setOrderNo(payOrder.getOrderNo());
        payRefund.setResult(result);
        payRefund.setChannel(payOrder.getChannel());
        payRefund.setPayType(payOrder.getPayType());
        payRefund.setPayAmount(payOrder.getPayAmount());
        payRefund.setRefundAmount(payOrder.getPayAmount());
        payRefund.setPayTime(payOrder.getPayTime());
        payRefund.setRefundTime(DateUtil.date());
        payRefund.insert();
    }

    public String sandRefund(PayOrder payOrder) {
        MallPayOrderRecord mallPayOrderRecord = new MallPayOrderRecord();
        mallPayOrderRecord.setTradeNo(UUID.fastUUID().toString(true));
        mallPayOrderRecord.setRefundAmount(payOrder.getPayAmount());
        mallPayOrderRecord.setNotifyUrl(SandConfig.MALL_REFUND_NOTIFY_URL);
        JSONObject jsonObject = SandPayUtil.refundRequest(mallPayOrderRecord, payOrder.getTradeNo(), "退款");
        JSONObject head= (JSONObject) jsonObject.get("head");
        String  respCode=(String)head.get("respCode");
        if (!respCode.equals("000000")) {
            throw new GlobalRunTimeException("杉德退款失败:"+head.get("respMsg"));
        }
        payOrder.setStatus(PayStatusEnum.INIT);
        payOrder.setRefundAmount(payOrder.getPayAmount());
        payOrder.updateById();
        return jsonObject.toJSONString();
    }
    
    public String otherRefund(PayOrder payOrder) {
        payOrder.setRefundTradeNo(OrderNoUtil.getOrderNo());
        JSONObject jsonObject=new JSONObject();
        switch (payOrder.getChannel()) {
            case HF_PAY:
                jsonObject=hfPayHelper.refund(payOrder.getUserId(),
                                payOrder.getTradeNo(), UUID.randomUUID().toString(true),payOrder.getPayTime(),payOrder.getPayAmount(),null,null );
                break;
            case LL_PAY:
                jsonObject=llPayHelper.refund(userInfoDao.getById(payOrder.getUserId()),payOrder.getTradeNo(), payOrder.getRefundTradeNo(),payOrder.getPayAmount().setScale(2, BigDecimal.ROUND_DOWN).toPlainString(),"",payOrder);
                break;
            case HNA_PAY:
                HnaRefundDto dto = new HnaRefundDto();
                dto.setOrderAmount(payOrder.getPayAmount().toString());
                dto.setRefundAmount(dto.getOrderAmount());
                dto.setRefundType("1");
                dto.setRemark("手动退款");
                dto.setOrgSubmitTime(DateUtil.format(payOrder.getCreateTime(),
                        DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
                dto.setOrgMerOrderId(payOrder.getTradeNo());
                dto.setNotifyUrl(hnaConfig.getT005NonMallNotifyUrl());
                UserInfo userInfo = new UserInfo();
                userInfo.setId(payOrder.getUserId());
                jsonObject= userHnaExtService.refund(userInfo, dto);
                break;
        }
        payOrder.setStatus(PayStatusEnum.INIT);
        payOrder.setRefundAmount(payOrder.getPayAmount());
        payOrder.updateById();
        return jsonObject.toJSONString();
    }
}
